package com.softstone.sng.client;

import com.jme3.app.SimpleApplication;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.network.Network;
import com.jme3.network.NetworkClient;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;
import com.softstone.sng.messages.PlayerMessage;
import com.softstone.sng.messages.SetupMessages;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * test
 *
 * @author Tomav
 */
public class Main extends SimpleApplication
{

  public static final String GAME_NAME = "Softstone's Network Game";
  public static final int GAME_VERSION = 1;
  private NetworkClient client;
  private Geometry myPlayer;
  private Map<Integer, Geometry> others = new HashMap<Integer, Geometry>();
  public static final Box box = new Box(Vector3f.ZERO, 1, 1, 1);
  public Material mat;

  public static void main(String[] args)
  {

    Main app = new Main();
    app.start();
  }

  public Main()
  {
    client = Network.createClient(Main.GAME_NAME, Main.GAME_VERSION);
    SetupMessages.register();
  }

  @Override
  public void simpleInitApp()
  {
    mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
    mat.setColor("Color", ColorRGBA.Blue);
    flyCam.setEnabled(false);
    MainAppState a = new MainAppState();
    stateManager.attach(a);
  }

  @Override
  public void destroy()
  {
    client.close();
    super.destroy();
  }

  public void playerChange(final PlayerMessage a_pm)
  {
    if (a_pm.getId() == client.getId())
    {
      myPlayer.setLocalTranslation(a_pm.getPosition());
      System.out.println(a_pm.getPosition());
    }
    else
    {
      if (a_pm.isActive() && others.containsKey(a_pm.getId()))
      {
        Logger.getLogger(Main.class.getName()).log(Level.SEVERE, "Player already exists");
        this.stop();
      }
      else
      {
        if (!a_pm.isActive())
        {
          try
          {
            enqueue(new Callable<Void>()
            {
              @Override
              public Void call() throws Exception
              {
                rootNode.detachChild(others.get(a_pm.getId()));
                return null;
              }
            }).get();
            others.remove(a_pm.getId());
          } catch (InterruptedException ex)
          {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
          } catch (ExecutionException ex)
          {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
          }
        }
        else
        {
          final Geometry g = new Geometry("" + a_pm.getId(), box);
          g.setMaterial(mat);
          g.setLocalTranslation(a_pm.getPosition());
          others.put(a_pm.getId(), g);
          enqueue(new Callable<Void>()
          {
            @Override
            public Void call() throws Exception
            {
              rootNode.attachChild(g);
              return null;
            }
          });
        }
      }

    }
  }

  public Geometry createMyPlayer()
  {
    myPlayer = new Geometry("MyPlayer", box);
    myPlayer.setMaterial(mat);
    myPlayer.addControl(new UserInputControl(inputManager));
    return myPlayer;
  }

  public Geometry getMyPlayer()
  {
    return myPlayer;
  }

  public Map<Integer, Geometry> getOthers()
  {
    return others;
  }

  public NetworkClient getClient()
  {
    return client;
  }
}
